#ifndef GAME_SIM_REGION_H
#define GAME_SIM_REGION_H

#include "game_entity.h"

// 模拟区域结构体，用于存储和管理实体
struct sim_region {
    world* World;
    // 最大实体半径，用于定义实体的最大影响范围
    real32 MaxEntityRadius;

    // 最大实体速度，用于限制实体的最大运动速度
    real32 MaxEntityVelocity;

    // Origin 存储模拟区域的中心位置，表示区域在世界坐标中的位置。
    world_position Origin;
    // Bounds 存储模拟区域的边界范围，定义了该区域的大小和形状，通常用于碰撞检测和边界检查。
    rectangle3 Bounds;

    // UpdateBounds：用于存储实体的更新区域边界。
    // 该矩形定义了实体的活动范围，在该范围内实体可以被更新。
    // 只有当实体位于这个矩形内时，它才会被标记为可更新。
    // 该矩形通常用于限定实体是否需要进行更新操作。
    rectangle3 UpdateBounds;

    uint32 MaxEntityCount;  // 最大实体数量，表示该区域可以容纳的最大实体数
    uint32 EntityCount;     // 当前实体数量，表示当前已存在的实体数
    entity* Entities;       // 指向实体数组的指针，用于存储该区域内的所有实体

    // GroundZBase: 用于表示地面层级的基准值。
    // 这个值作为地面层的参考点，用于确定角色当前所在的地面高度。
    // 通过该基准值，可以将角色的当前位置`z`坐标截断到最近的地面层，进而计算出角色的实际地面高度。
    // 它有助于在多层地面环境中处理角色的地面定位和碰撞。
    real32 GroundZBase;

    uint32 MaxBrainCount;
    uint32 BrainCount;
    brain* Brains;

    entity_hash EntityHash[4096];
    brain_hash BrainHash[256];
};

enum traversable_search_flag {
    TraversableSearch_Unoccupied = 0x1,
};
struct closest_entity {
    entity* Entity;
    v3 Delta;
    real32 DistanceSq;
};

sim_region* BeginSim(memory_arena* SimArena, world* World, world_position Origin, rectangle3 Bounds,
                     real32 dt);
void EndSim(sim_region* Region, game_mode_world* WorldMode);
void UpdateMonster(sim_region* SimRegion, entity* Entity, real32 dt);
bool32 GetClosestTraversable(sim_region* SimRegion, v3 FromP, traversable_reference* Result,
                             uint32 Flags = 0);
entity_traversable_point GetSimSpaceTraversable(traversable_reference Reference);
void PackTraversableReference(sim_region* SimRegion, traversable_reference* Ref);
void PackEntityReference(sim_region* SimRegion, entity_reference* Ref);
bool32 TransactionalOccupy(entity* Entity, traversable_reference* DestRef,
                           traversable_reference DesiredRef);
bool32 IsOccupied(traversable_reference Ref);
bool32 GetClosestTraversableAlongRay(sim_region* SimRegion, v3 FromP, v3 Dir,
                                     traversable_reference Skip, traversable_reference* Result,
                                     uint32 Flags = 0);
closest_entity GetClosestEntityWithBrain(sim_region* SimRegion, v3 P, brain_type Type,
                                         real32 MaxRadio = 20.0f);
#endif